package com.tarena.lbs.marketing.web.service;

import com.alibaba.nacos.common.utils.CollectionUtils;
import com.github.pagehelper.PageInfo;
import com.tarena.lbs.base.common.utils.Asserts;
import com.tarena.lbs.base.protocol.exception.BusinessException;
import com.tarena.lbs.base.protocol.pager.PageResult;
import com.tarena.lbs.basic.api.BasicApi;
import com.tarena.lbs.common.passport.enums.Roles;
import com.tarena.lbs.common.passport.principle.UserPrinciple;
import com.tarena.lbs.common.security.utils.LbsSecurityContenxt;
import com.tarena.lbs.marketing.web.repository.CouponCodeRepository;
import com.tarena.lbs.marketing.web.repository.CouponRepository;
import com.tarena.lbs.pojo.basic.dto.AdminDTO;
import com.tarena.lbs.pojo.marketing.param.CouponParam;
import com.tarena.lbs.pojo.marketing.po.CouponCodePO;
import com.tarena.lbs.pojo.marketing.po.CouponPO;
import com.tarena.lbs.pojo.marketing.query.CouponQuery;
import com.tarena.lbs.pojo.marketing.vo.CouponVO;
import com.tarena.lbs.pojo.stock.param.CouponStockParam;
import com.tarena.lbs.stock.api.StockApi;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

@Service
@Slf4j
public class CouponService {
    @Autowired
    private CouponRepository couponRepository;
    @Autowired
    private CouponCodeRepository couponCodeRepository;
    @DubboReference
    private BasicApi basicApi;
    @DubboReference
    private StockApi stockApi;
    public PageResult<CouponVO> couponPage(CouponQuery query) throws BusinessException {
        //1、获取认证对象 判断存在
        UserPrinciple userPrinciple = LbsSecurityContenxt.getLoginToken();
        Asserts.isTrue(userPrinciple== null,new BusinessException("-2","用户认证失败"));
        //2、判断角色 SHOP 条件里封装businessId USER 角色异常结束 ADMIN 角色什么都不做
        Asserts.isTrue(userPrinciple.getRole() == Roles.USER,new BusinessException("-2","普通用户不能查询优惠券"));
        if (userPrinciple.getRole()== Roles.SHOP){
            // 2.1 SHOP 商家账号查询调用basic接口
            Integer adminId=userPrinciple.getId();
            AdminDTO adminDetail = basicApi.getAdminDetail(adminId);
            Asserts.isTrue(adminDetail==null,new BusinessException("-2","商家账号异常"));
            query.setBusinessId(adminDetail.getBusinessId());
        }
        //2.2 AdminPO商家账号详细数据不为空 补条件bizId
        //3.调用数据层返回分页数据
        // 查询优惠券信息分页数据
        // 根据给定的查询条件，通过 couponRepository 获取分页后的 CouponPO 列表
        PageInfo<CouponPO> pageInfo= couponRepository.getCouponsByPage(query);
        // 创建一个分页结果对象用于存放转换后的优惠券视图对象
        PageResult<CouponVO> voPage=new PageResult<>();
        // 设置分页结果的当前页码
        voPage.setPageNo(pageInfo.getPageNum());
        // 设置分页结果的页面大小
        voPage.setPageSize(pageInfo.getPageSize());
        // 设置分页结果的总记录数
        voPage.setTotal(pageInfo.getTotal());
        // 定义一个 CouponVO 的列表，用于存放转换后的优惠券视图对象
        List<CouponVO> vos=null;
        if (CollectionUtils.isNotEmpty(pageInfo.getList())){
            vos=pageInfo.getList().stream().map(po->{
                CouponVO vo=new CouponVO();
                BeanUtils.copyProperties(po,vo);
                return vo;
            }).collect(Collectors.toList());
        }
        voPage.setObjects(vos);
        return voPage;
    }
    //DAY12-PM 01优惠券表单新增提交
    public void couponSave(CouponParam param) throws BusinessException, ParseException {
        //1.获取认证对象
        UserPrinciple userPrinciple = LbsSecurityContenxt.getLoginToken();
        Asserts.isTrue(userPrinciple==null,new BusinessException("-2","用户认证失败"));
        //2.只有商家账号可以新增
        Asserts.isTrue(userPrinciple.getRole()!=Roles.SHOP,new BusinessException("-2","新增优惠券权限不足"));
        //3.调用basic接口查询商家账号信息 为了补充优惠券表单数据
        AdminDTO adminDTO=basicApi.getAdminDetail(userPrinciple.getId());
        Asserts.isTrue(adminDTO==null,new BusinessException("-2","商家账号异常"));
        //4.封装CouponPO准备 写入到数据库
        CouponPO poParam=assembleCouponPO(param,adminDTO.getBusinessId());
        //5.调用优惠券数据层写入到优惠券表格
        couponRepository.saveCoupon(poParam);
        //6.写入优惠券发送总量的券码到 coupon_code 同步调用
        List<CouponCodePO> codePoParams=assembleCouponCodePos(poParam);
        //7.执行批量写入
        couponCodeRepository.saveBatch(codePoParams);
        //TODO 8.远程调用stock服务同步优惠券库存(发送总量一样数据)
        initCouponStock(poParam);
    }
    //6.写入优惠券发送总量的券码到 coupon_code 同步调用
    private List<CouponCodePO> assembleCouponCodePos(CouponPO poParam) {
        //1.获取到发行总量
        Integer total = poParam.getMaxUsageLimit();
        //2.准备一个集合
        List<CouponCodePO> pos=new ArrayList<>();
        //??total数字很大 循环 时间越长
        for (Integer i = 0; i < total; i++){
            // 创建一个新的优惠码持久化对象
            CouponCodePO po=new CouponCodePO();
            // 设置业务ID，对应poParam中的业务ID
            po.setBusinessId(poParam.getBusinessId());
            // 设置优惠券ID，对应poParam中的优惠券I
            po.setCouponId(poParam.getId());
            //新增添的优惠券状态0待使用
            po.setStatus(0);
            // 设置创建时间，与poParam中的创建时间一致
            po.setCreateAt(poParam.getCreateAt());
            // 设置更新时间，与poParam中的更新时间一致
            po.setUpdateAt(poParam.getUpdateAt());
            //每一个优惠券券码code编码都是唯一值
            po.setCouponCode(UUID.randomUUID().toString());
            pos.add(po);
        }
        return pos;
    }

    //封装CouponPO准备 写入到数据库
    private CouponPO assembleCouponPO(CouponParam param, Integer businessId) throws ParseException {
        //1.将表单参数 能拷贝的全拷贝
        CouponPO poParam=new CouponPO();
        BeanUtils.copyProperties(param,poParam);
        //2.单独填补一些不存在的数据
        //2.1优惠券所属商家
        poParam.setBusinessId(businessId);
        //2.2优惠券状态 待激活0,待使用1,过期2,作废3
        poParam.setStatus(1);
        //2.3优惠券管理状态 启用0 禁用1
        poParam.setEnableStatus(0);
        //3.优惠券数据库通用字段时间
        poParam.setCreateAt(new Date());
        poParam.setUpdateAt(poParam.getCreateAt());
        //4.前端为了方便 传递的startTime endTime时间是字符串 需要转换成Date类型
        //时间字符串格式 yyyy-MM-dd HH:mm:ss
        poParam.setStartDate(DateUtils.parseDate(param.getStartDate(),"yyyy-MM-dd HH:mm:ss"));
        poParam.setEndDate(DateUtils.parseDate(param.getEndDate(),"yyyy-MM-dd HH:mm:ss"));
        return poParam;
    }

    private void initCouponStock(CouponPO poParam) throws BusinessException {
        //1.利用couponPo 组织初始化库存的param
        CouponStockParam param=new CouponStockParam();
        param.setBusinessId(poParam.getBusinessId());
        param.setCouponId(poParam.getId());
        param.setNum(poParam.getMaxUsageLimit());
        //2.调用库存服务
        boolean result = stockApi.initCouponStock(param);
        Asserts.isTrue(!result,new BusinessException("-2","库存初始化失败"));
        //log.info(" 后续实现库存同步");
    }

    public CouponVO couponDetail(Integer id) {
        CouponPO po=couponRepository.getCouponById(id);
        CouponVO vo=null;
        if (po!=null){
            vo=new CouponVO();
            BeanUtils.copyProperties(po,vo);
        }
        return vo;
    }
}
